package com.helloworld.demo.atomic.casshare;


import sun.misc.Unsafe;

import java.lang.reflect.Field;
import java.util.concurrent.CountDownLatch;


/**
 *  1.CAS基本概念
 * 	2.CAS+自旋加锁
 * 	3.CAS使用到了什么指令
 * 	4.CAS可能出现的问题
 *
 * 	场景：一次请求，访问量加一，模拟100个人同时访问，最终访问量应该是100
 *
 * 	JDK1.8
 *
 *
 *
 *
 *
 *
 *
 * 1.CAS(CompareAndSwap) 比较并交换
 *   CAS包含三个操作数，内存地址，期望值，新值           内存地址的值与期望值相同则更新值，否则CPU不做任何操作
 *
 * 3.JAVA中对CAS操作的支持，sun.misc.Unsafe类
 *
 *   public final native boolean compareAndSwapObject(Object var1, long var2, Object var4, Object var5);
 *   public final native boolean compareAndSwapInt(Object var1, long var2, int var4, int var5);
 *   public final native boolean compareAndSwapLong(Object var1, long var2, long var4, long var6);
 *
 *   native 这里JNI使用C/C++调用了CPU的cmpxchg指令（Intel x86）,该指令在CPU层面保证原子性
 *

 * 4.CAS 可能出现ABA问题
 *       解决方案是添加版本号：AtomicStampedReference
 *
 *
 *
 *
 *
 *
 *
 */
public class CASConcurrencyMock {

    private static Unsafe unsafe;

    static {
        try {
            Field theUnsafeField = Unsafe.class.getDeclaredField("theUnsafe");
            theUnsafeField.setAccessible(true);
            unsafe = (Unsafe) theUnsafeField.get(null);

        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) throws InterruptedException {
        long start = System.currentTimeMillis();

        CountDownLatch countDownLatch = new CountDownLatch(100);

        WebVisit webVisit = new WebVisit();


        //模拟100个用户访问
        for (int i = 0;i < 100;i++){
            new Thread(()->{
                try {
                    requestMockCAS(webVisit);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } catch (NoSuchFieldException e) {
                    e.printStackTrace();
                } finally {
                    countDownLatch.countDown();
                }
            }).start();
        }

        //保证100个线程执行完毕
        countDownLatch.await();

        long end = System.currentTimeMillis();

        System.out.println("耗时：" + (end - start) + " ,访问量：" + webVisit.count);


    }


    private static void requestMockCAS(WebVisit webVisit) throws InterruptedException, NoSuchFieldException {
        //体现抢占效果
        Thread.sleep(8);

        Field count = webVisit.getClass().getDeclaredField("count");
        long offset = unsafe.objectFieldOffset(count);

        while(!unsafe.compareAndSwapInt(webVisit, offset, webVisit.count, webVisit.count + 1));

        //webVisit.count++;

    }


}

class WebVisit{

    //网站访问量
     //int count = 0;
    volatile int count = 0;
}